home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
filesyst
/
thsfs.tgz
/
thsfs.tar
/
thsfs
/
super.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-04
|
8KB
|
381 lines
/*************************************************************
* *
* ths Filesystem 04.10.94 V1.1 *
* *
* Thomas Scheuermann ths@ai-lab.fh-furtwangen.de *
* *
*************************************************************/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/mm.h>
#include <linux/locks.h>
#include <linux/fs.h>
#include <linux/malloc.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/bitops.h>
#include "ths.h"
#include "ths_i.h"
static struct super_operations ths_sops = {
ths_read_inode,
NULL,
NULL,
NULL,
ths_put_super,
NULL,
ths_statfs,
NULL
};
/*
* Lesen des MSDOS-Bootblocks und Ausfuellen der
* super_block Struktur
*/
struct super_block *ths_read_super(struct super_block *s, void *data, int silent)
{
struct ths_sb_info *ths_sb;
ths_sb = (struct ths_sb_info *)kmalloc(512,GFP_KERNEL);
s->u.generic_sbp = ths_sb;
if(data==NULL)
{
ths_sb->art=0; /* normales DOS */
return ths_read_super_normal(s,data,silent);
}
else
{
ths_sb->art=1; /* DoubleSpace */
return ths_read_super_dblspace(s,data,silent);
}
}
/*
* Lesen des Super-Blocks fuer DoubleSpace-Laufwerke
*/
struct super_block *ths_read_super_dblspace(struct super_block *s, void *data, int silent)
{
struct buffer_head *bh;
struct ths_boot_sektor *bs;
struct dbl_boot_sektor *dbl;
struct ths_sb_info *ths_sb;
char *data1=NULL;
long RootStart;
ths_sb = (struct ths_sb_info *)s->u.generic_sbp;
#ifdef DEBUG
printk("DoubleSpace-Superblock\n");
#endif
lock_super(s);
bh = bread(s->s_dev,0,BLOCK_SIZE);
if (bh == NULL)
{
s->s_dev = 0;
printk("ths bread failed\n");
unlock_super(s);
return NULL;
}
bs = (struct ths_boot_sektor *)bh->b_data;
ths_sb->uFATStart = CHS(bs->ReservierteSektoren);
ths_sb->uDatenStart = CHS(bs->ReservierteSektoren) +
(bs->AnzahlFats * CHS(bs->SektorenProFat)) +
(CHS(bs->EintraegeRootverzeichnis) / 16);
ths_sb->uSektorenProCluster = bs->SektorenProCluster;
ths_sb->uAnzahlCluster = (short)(((CHS(bs->SektorenImVolume) ? CHS(bs->SektorenImVolume) :
CHL(bs->SektorenImVolume2)) -
CHS(bs->ReservierteSektoren) -
(bs->AnzahlFats * CHS(bs->SektorenProFat)) -
(CHS(bs->EintraegeRootverzeichnis) / 16)) /
bs->SektorenProCluster);
ths_sb->uBitsProCluster = ths_sb->uAnzahlCluster < 4078 ? 12 : 16;
RootStart = CHS(bs->ReservierteSektoren) +
(bs->AnzahlFats * CHS(bs->SektorenProFat));
ths_sb->StartCluster = findeStartCluster(s,RootStart,CHS(bs->EintraegeRootverzeichnis),data);
if(ths_sb->StartCluster == 0)
{
printk("CVF nicht gefunden !!\n");
brelse(bh);
unlock_super(s);
return NULL;
}
#ifdef DEBUG
printk("StartCluster : %d\n",ths_sb->StartCluster);
#endif
unlock_super(s);
data1 = ths_uread(s,0,&bh);
bs = (struct ths_boot_sektor *)data1;
superfill(s,ths_sb,bs);
dbl = (struct dbl_boot_sektor *)data1;
ths_sb->BitFATStart = 1;
ths_sb->MDFATStart = (long)CHS(dbl->MDFATStart)+1;
ths_sb->BootStart = (long)CHS(dbl->res0);
ths_sb->FatStart = (long)(CHS(dbl->res0)+CHS(dbl->ReservierteSektoren));
ths_sb->RootStart = (long)(CHS(dbl->res0) + CHS(dbl->RootDirStart));
ths_sb->DatenStart = (long)(CHS(dbl->res0) + CHS(dbl->DatenStart)+2);
ths_sb->AnzahlCluster = ths_sb->AnzahlCluster*8;
ths_sb->dcluster = CHS(dbl->ClusterStart);
#ifdef DEBUG
printk("BitFATStart : %ld\n",ths_sb->BitFATStart);
printk("MDFATStart = %ld\n",ths_sb->MDFATStart);
printk("BootStart : %ld\n",ths_sb->BootStart);
printk("FatStart : %ld\n",ths_sb->FatStart);
printk("RootDirStart = %ld\n",ths_sb->RootStart);
printk("DatenStart = %ld\n",ths_sb->DatenStart);
printk("Anzahl Cluster = %d\n",ths_sb->AnzahlCluster);
printk("dev : %d\n",s->s_dev);
#endif
brelse(bh);
cvffill(s);
fatmem2(s);
s->s_blocksize = BLOCK_SIZE;
s->s_blocksize_bits = 10;
s->s_op = &ths_sops;
s->s_mounted = iget(s,1);
return s;
}
/*
* Lesen des Super-Blocks fuer normale DOS-Laufwerke
*/
struct super_block *ths_read_super_normal(struct super_block *s, void *data, int silent)
{
struct buffer_head *bh;
struct ths_boot_sektor *bs;
struct ths_sb_info *ths_sb;
#ifdef DEBUG
printk("read_super\n");
printk("Daten : %s\n",(char *)data);
#endif
/*
* Lesen des Bootblocks
*/
lock_super(s);
bh = bread(s->s_dev,0,BLOCK_SIZE);
if (bh == NULL)
{
s->s_dev = 0;
printk("ths bread failed\n");
unlock_super(s);
return NULL;
}
bs = (struct ths_boot_sektor *)bh->b_data;
ths_sb = (struct ths_sb_info *)s->u.generic_sbp;
/*
* Fuellen der Struktur
*/
superfill(s,ths_sb,bs);
unlock_super(s);
brelse(bh);
fatmem2(s);
s->s_blocksize = BLOCK_SIZE;
s->s_blocksize_bits = 10;
s->s_op = &ths_sops;
s->s_mounted = iget(s,1);
#ifdef DEBUG
printk("dev : %d\n",s->s_dev);
#endif
return s;
}
/*
* Informationen aus dem Superblock extrahieren.
*/
void superfill(struct super_block *s,struct ths_sb_info *ths_sb,struct ths_boot_sektor *bs)
{
s->s_magic = THS_MAGIC;
ths_sb->SektorenProCluster = bs->SektorenProCluster;
ths_sb->SektorenProFat = CHS(bs->SektorenProFat);
ths_sb->AnzahlCluster = (short)(((CHS(bs->SektorenImVolume) ? CHS(bs->SektorenImVolume) :
CHL(bs->SektorenImVolume2)) -
CHS(bs->ReservierteSektoren) -
(bs->AnzahlFats * CHS(bs->SektorenProFat)) -
(CHS(bs->EintraegeRootverzeichnis) / 16)) /
bs->SektorenProCluster);
ths_sb->BitsProCluster = ths_sb->AnzahlCluster < 4078 ? 12 : 16;
ths_sb->FatStart = CHS(bs->ReservierteSektoren);
ths_sb->RootMaxEintraege = CHS(bs->EintraegeRootverzeichnis);
ths_sb->DatenStart = CHS(bs->ReservierteSektoren) +
(bs->AnzahlFats * CHS(bs->SektorenProFat)) +
(CHS(bs->EintraegeRootverzeichnis) / 16);
ths_sb->RootStart = CHS(bs->ReservierteSektoren) +
(bs->AnzahlFats * CHS(bs->SektorenProFat));
#ifdef DEBUG
printk("SektorenProCluster :%i\n",ths_sb->SektorenProCluster);
printk("SektorenProFat :%i\n",ths_sb->SektorenProFat);
printk("Sektoren1 : %d\n",CHS(bs->SektorenImVolume));
printk("Sektoren2 : %ld\n",CHL(bs->SektorenImVolume2));
printk("AnzahlCluster :%d\n",ths_sb->AnzahlCluster);
printk("BitsProCluster :%d\n",ths_sb->BitsProCluster);
printk("FatStart :%ld\n",ths_sb->FatStart);
printk("RootMaxEintraege :%d\n",ths_sb->RootMaxEintraege);
printk("DatenStart :%ld\n",ths_sb->DatenStart);
printk("RootStart :%ld\n",ths_sb->RootStart);
#endif
}
/*
* Suche nach dem Startcluster des CVF
*/
short findeStartCluster(struct super_block *s,long Rootdir, short Eintraege, char *name)
{
int i,j;
char *data=NULL;
struct buffer_head *bh=NULL;
struct ths_dir *dir;
for(j=0;name[j]!='\0';j++);
#ifdef DEBUG
printk("%s : %d\n",name,j);
#endif
for(i=0;i<Eintraege*32;)
{
if(!(i&0x1ff))
{
data = ths_uread_sektor(Rootdir+i/512,s->s_dev,&bh);
}
dir = (struct ths_dir *)&data[i%512];
if(vergleich(dir,(const char *)name,j))
{
brelse(bh);
return CHS(dir->cluster);
}
i+=32;
if(!(i&0x1ff))
brelse(bh);
}
return 0;
}
void ths_put_super(struct super_block *s)
{
#ifdef DEBUG
printk("put_super\n");
#endif
lock_super(s);
fatfree(s);
cvffree(s);
kfree_s(s->u.generic_sbp,512);
s->s_dev=0;
unlock_super(s);
return;
}
void ths_statfs(struct super_block *s, struct statfs *buf)
{
struct ths_sb_info *ths_sb;
long i,j,k;
short *addr;
#ifdef DEBUG
printk("statfs\n");
#endif
ths_sb = (struct ths_sb_info *)s->u.generic_sbp;
put_fs_long(THS_MAGIC, &buf->f_type);
put_fs_long(1024, &buf->f_bsize);
put_fs_long(ths_sb->AnzahlCluster*ths_sb->SektorenProCluster/2, &buf->f_blocks);
j=0;
/*
* k wird auf 2 gesetzt, da die ersten beide Eintraege
* der FAT keine Cluster-Zeiger sind.
*/
k=2;
addr=ths_sb->fat[0];
for (i=0;i<ths_sb->AnzahlCluster;i++)
{
if(addr[k]==0)
j++;
k++;
if(k==2048)
{
k=0;
addr=ths_sb->fat[(i+3)/2048];
}
}
j*=ths_sb->SektorenProCluster;
j/=2;
#ifdef DEBUG
printk("frei : %ld\n",j);
#endif
put_fs_long(j, &buf->f_bfree);
put_fs_long(j, &buf->f_bavail);
}